<?php

namespace app\controller;

use app\service\WxShopService;
use support\Log;
use support\Request;

class WxshopNotifyController
{
    protected array $noNeedLogin = ['notify'];

    private string $token;
    private string $encodingAESKey;
    private string $wxshopAppId;

    public function __construct()
    {
        // 从 .env 文件读取配置
        $this->token = env('WX_SHOP_PUSH_TOKEN', '');
        $this->encodingAESKey = env('WX_SHOP_MESSAGE_SECRET', '');
        $this->wxshopAppId = env('WX_SHOP_APPID', '');
    }

    /**
     * 微信小店推送回调入口
     */
    public function notify(Request $request)
    {
        // 获取 URL 参数
        $msg_signature = $request->get('msg_signature', '');
        $timestamp = $request->get('timestamp', '');
        $nonce = $request->get('nonce', '');

        // 获取原始请求体
        $rawBody = $request->rawBody();
        $postArray = json_decode($rawBody, true);

        if (!isset($postArray['Encrypt'])) {
            Log::error('微信推送失败：缺少 Encrypt 字段，原始数据：' . $rawBody);
            return 'fail: missing Encrypt';
        }

        $encrypt = $postArray['Encrypt'];

        // 验证签名是否合法
        if (!$this->checkSignature($this->token, $timestamp, $nonce, $encrypt, $msg_signature)) {
            Log::error('微信推送签名验证失败', [
                'token' => $this->token,
                'timestamp' => $timestamp,
                'nonce' => $nonce,
                'encrypt' => $encrypt,
                'msg_signature' => $msg_signature
            ]);
            return 'fail: signature error';
        }

        // 解密加密内容
        $plainText = $this->decrypt($encrypt, $this->encodingAESKey);
        if ($plainText === false) {
            Log::error('微信推送解密失败', [
                'encrypt' => $encrypt,
                'aes_key' => $this->encodingAESKey
            ]);
            return 'fail: decrypt error';
        }

        // 解析解密后的明文内容
        $data = $this->parsePlainText($plainText);
        if ($data === false) {
            Log::error('微信推送明文解析失败', [
                'plainText' => $plainText
            ]);
            return 'fail: parse plaintext error';
        }

        // 校验 AppID 是否一致
        if ($data['appid'] !== $this->wxshopAppId) {
            Log::error('微信推送 AppID 校验失败', [
                'expected' => $this->wxshopAppId,
                'got' => $data['appid']
            ]);
            return 'fail: appid mismatch';
        }

        //业务处理
        if (isset($data['message']['Event'])) {
            $event = $data['message']['Event'];
            switch ($event) {
                case 'channels_ec_order_pay':
                case 'channels_ec_order_deliver':
                case 'channels_ec_order_confirm':
                case 'channels_ec_order_settle':
                    $order_id = $data['message']['order_info']['order_id'];
                    break;
                case 'channels_ec_aftersale_update':
                    $order_id = $data['message']['finder_shop_aftersale_status_update']['order_id'];
                    $EcAftersaleInfoStatus =  $data['message']['finder_shop_aftersale_status_update']['status'];
                    if ($EcAftersaleInfoStatus !== 'MERCHANT_REFUND_SUCCESS'){
                        return false;
                    }
                    break;
                case 'channels_ec_guarantee_update':
                    $order_id = $data['message']['finder_shop_guarantee_status_update']['order_id'];
                    $GuaranteeStatus = $data['message']['finder_shop_guarantee_status_update']['status'];
                    if ($GuaranteeStatus !== 'STATUS_PAY_SUCC'){
                        return false;
                    }
                    break;
                default:
                    $order_id = null;
            }
            if($order_id){
                var_dump($data['message']);
                Log::info(json_encode($data['message'],true));

                (new WxShopService())->wxShopOrderUpdate($event, $order_id);
            }

        }


        // 处理成功响应
        return json_encode([
            'code' => 0,
            'msg' => 'success',
            'data' => $data['message']
        ], JSON_UNESCAPED_UNICODE);
    }

    /**
     * 验证签名是否合法
     */
    private function checkSignature(string $token, string $timestamp, string $nonce, string $encrypt, string $msg_signature): bool
    {
        $tmpArr = [$token, $timestamp, $nonce, $encrypt];
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $sha1 = sha1($tmpStr);
        return $sha1 === $msg_signature;
    }

    /**
     * 解密加密内容，使用 AES-256-CBC 算法
     */
    private function decrypt(string $encrypt, string $encodingAESKey)
    {
        $aesKey = base64_decode($encodingAESKey . '=');
        if (strlen($aesKey) !== 32) {
            Log::error('AESKey 长度错误：' . strlen($aesKey));
            return false;
        }

        $ciphertext = base64_decode($encrypt);
        if ($ciphertext === false) {
            Log::error('Encrypt Base64 解码失败');
            return false;
        }


        $iv = substr($aesKey, 0, 16);

        $decrypted = openssl_decrypt($ciphertext, 'AES-256-CBC', $aesKey, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);


        // 手动去除 PKCS#7 填充
        $pad = ord(substr($decrypted, -1));
        if ($pad > 0 && $pad <= 32) {
            $decrypted = substr($decrypted, 0, -$pad);
        }

        if ($decrypted === false) {
            Log::error('OpenSSL 解密失败');
            return false;
        }

        return $decrypted;
    }

    /**
     * 拆解明文字符串，提取消息 JSON 和 AppID
     */
    private function parsePlainText(string $plainText)
    {
        $totalLen = strlen($plainText);
        if ($totalLen < 20) {
            return false;
        }

        $content = substr($plainText, 16); // 跳过前16字节随机串
        $msg_len_bin = substr($content, 0, 4); // 取消息长度
        $msg_len = unpack('N', $msg_len_bin)[1]; // 网络字节序

        $msg = substr($content, 4, $msg_len);
        $appid = substr($content, 4 + $msg_len);
        $appid = trim($appid);

        $message = json_decode($msg, true);
        if (!$message) {
            Log::error('JSON 解析失败：' . $msg);
            return false;
        }

        return [
            'message' => $message,
            'appid' => $appid
        ];
    }
}
